import math

import cv2
import cv2 as  cv
import numpy as np
import Home

import matplotlib.pyplot as plt

#region 无用函数

# #边缘检测
# def canny(image):
#     img_color = image
#     blur = cv2.GaussianBlur(image, (3, 3), 0)  # 用高斯滤波处理原图像降噪
#     canny = cv2.Canny(blur, 50, 200)  # 50是最小阈值,150是最大阈值
#     cv2.namedWindow("canny", 0);  # 可调大小
#     cv2.namedWindow("1", 0);  # 可调大小
#     cv2.imshow('1', image)
#     cv2.imshow('canny', canny)
#     cv2.waitKey(0)
#     cv2.destroyAllWindows()

# # 转置矩阵
# def transformMatrix(m):
#     rt = [[] for i in m[0]]    # m[0] 有几个元素，说明原矩阵有多少列。此处创建转置矩阵的行
#     for ele in m:
#         for i in range(len(ele)):
#             # rt[i] 代表新矩阵的第 i 行
#             # ele[i] 代表原矩阵当前行的第 i 列
#             rt[i].append(ele[i])
#     return rt

# #没什么用
# def shape_process(image):
#     # 2. cv2.MORPH_OPEN 先进行腐蚀操作，再进行膨胀操作
#     kernel = np.ones((5, 5), np.uint8)
#     opening = cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel)
#     cv2.imshow('opening', opening)
#
#     # 3. cv2.MORPH_CLOSE 先进行膨胀，再进行腐蚀操作
#     kernel = np.ones((5, 5), np.uint8)
#     closing = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernel)
#     cv2.imshow('closing', closing)
#
#     cv2.waitKey(0)
#
#
#     '''kernel = np.ones((10, 10), np.uint8)
#     edge_img1 = cv2.morphologyEx(edge_img, cv2.MORPH_CLOSE, kernel)
#     edge_img2 = cv2.morphologyEx(edge_img1, cv2.MORPH_OPEN, kernel)
#     contours, hierarchy = cv2.findContours(edge_img2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
#
#     cv2.imshow('shape_process_1', edge_img1)
#     cv2.imshow('shape_process_2', edge_img2)
#     cv2.waitKey(0)
#     return edge_img2'''

#返回灰度图像
def grayscale(image):
    image=cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    if np.sum(image[5:10,5:10])>4000:
        image[:, :] = 255 - image[:, :]
    return image

#二值化
def threshold(image):
    ret, image = cv2.threshold(image, 100, 225, cv2.THRESH_BINARY)
    '''cv2.imshow(Home.image_name, image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()'''
    if(ret == False):
        print('Error in thresholding')
    else:
        return image

#腐蚀膨化
def fushi(img):
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))  # 定义一个10x10的矩形核
    erode = cv2.erode(img, kernel, 5)
    dilate = cv2.dilate(img, kernel, 5)
    #cv2.imshow('erode', erode)  # 显示腐蚀图像
    #cv2.imshow('dilate', dilate)  # 显示膨胀图像
    #cv2.waitKey(0)  # 保持图像
    '''cv2.imshow(Home.image_name, dilate)
    cv2.waitKey(0)
    cv2.destroyAllWindows()'''
    return dilate

# # 转置矩阵
# def transformMatrix(m):
#     rt = [[] for i in m[0]]    # m[0] 有几个元素，说明原矩阵有多少列。此处创建转置矩阵的行
#     for ele in m:
#         for i in range(len(ele)):
#             # rt[i] 代表新矩阵的第 i 行
#             # ele[i] 代表原矩阵当前行的第 i 列
#             rt[i].append(ele[i])
#     return rt

#880*550
# def search_origin_point(image):
#     image=grayscale(image)
#     print(image.shape[0])
#     histogram = np.sum(image, axis=0)
#
#
#     print(len(histogram))
#     print(histogram[:20])
#     print(histogram[50:120])
#     print(len(image[0]))
#
#
#     for i in range(10,len(histogram)-50):
#         if (histogram[i]==histogram[i+1]&histogram[i]==histogram[i+2]&histogram[i]!=histogram[3]):
#             index=i;
#             image_show=image.copy()
#             for j in range(image.shape[0]-1):
#                 image_show[j][index]=0
#
#             #转置image数组
#             print(len(image[0]))
#             #转置函数
#             image_T=image.transpose()
#             print("image[0]",len(image_T[0]))
#
#
#             #统计数组中颜色分类个数
#             myset=set(image_T[index]);
#             for item in myset:
#                 print(item,np.sum(image_T[index]==item))
#             print(index)
#
#             break
#     cv2.imshow("adsf",image_show)
#     cv2.imshow("adsffdf", image)
#     cv2.waitKey(0)
#
#     #寻找颜色横线
#     #print(image)



#step 1：判断横坐标数字位置，确定数字大小
def local_number_down(image):
    image_gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)

    # region Step 1 先找到纵坐标数字的那一列
    start, end = 0, 0  # 左边一列的数字
    down ,up= 0,0  # 下面的数字底部位置
    number_top,number_down=0,0#底部数字的上下边

    number_high=0

#画竖线
    histogram_row = np.sum(image_gray, axis=1)  # 每一行相加
    for i in range(10,image.shape[0]-10):
        if abs(histogram_row[i] -histogram_row[i+1])>255:
            up = i
            break
    for i in range(image.shape[0]-10,10,-1):
        if abs(histogram_row[i] -histogram_row[i-1])>255:
            down = i-1
            #计算数字高度
            for j in  range(i-1,10,-1):
                if histogram_row[j]==histogram_row[i+1]:
                    number_top=j
                    break
            break
# 画横线
    histogram = np.sum(image_gray, axis=0)  # 每一列相加
    for i in range(10, len(histogram)-10):
        if abs(histogram[i] -histogram[i+1])>255:
            start = i
            break
    for i in range(len(histogram)-10,10,-1):
        if abs(histogram[i] -histogram[i+1])>255:
            end = i
            break



#找到横坐标数字0
    zero_start,zero_end=0,0
    for i in range(10,image.shape[1]-10):
        if image_gray[down,i]>image_gray[10,10]:
            zero_start=i
            for j in range(i,i+20):
                if image_gray[down,j]==image_gray[10,10]:
                    zero_end=j-1
                    break
            break
    zero_mid=(zero_end+zero_start)//2
    number_high=abs(number_top-number_down)

    print("zero",zero_mid)
    image[down, :, :] = 255
    image[up, :, :] = 255
    image[number_top, :, :] = 255
    image[:, start, :] = 255
    image[:, end, :] = 255
    image[:, zero_mid, :] = 255
    image[:, zero_start, :] = 120
    image[:, zero_end, :] = 120

    cv.imshow("fen_ge_qu_xan.bu.fen"+Home.image_name, image)
   #返回    图片划线，左边数字开始位置，右边竖线位置，左边竖线位置，下边数字下方位置，上面位置，数字高度
    return image,start,end,zero_mid,down,up,number_high




#定位1,-失败
def locate(image):
    car_plates = []
    #找出轮廓
    contours, hierarchy = cv2.findContours(image, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    for contour in contours:
        if cv2.contourArea(contour) > 500:  # 这个500参数和图片大小有关，本文经验值
            rect_tupple = cv2.minAreaRect(contour)
            rect_width, rect_height = rect_tupple[1]
            if rect_width < rect_height:
                rect_width, rect_height = rect_height, rect_width
            aspect_ratio = rect_width / rect_height
            # 车牌正常情况下宽高比在2 - 5.5之间
            if aspect_ratio > 0.3 and aspect_ratio < 1.5:
                car_plates.append(contour)
    image_cai =np.ones((image.shape[0], image.shape[1], 3), np.uint8)
    #print("car_plates[0][0]",car_plates[0][0])
    #print(image_cai[0][0])
    image_cai2=image_cai.copy()
    for i in image_cai2:
        for j in i :
            j=[255,0,0]
    print("image_cai2",image_cai2)
    #image_cai2.fill([255,0,0])
    for item0 in  car_plates:
        for item in item0 :
            print("item[0]",item[0])
            print("image_cai2[item[0][1],item[0][0]]",image_cai2[item[0][1],item[0][0]])
            image_cai2[item[0][1],item[0][0]]=[255,0 ,0]
    '''cv2.imshow('image_cai', image_cai2)
    cv2.waitKey(0)'''
    #print(image_cai[car_plates[:][:][:][0]][car_plates[:][:][:][1]])

def search_line(image):
    left=image.shape[1]//2
    bottom=image.shape[0]//2
    img=image[50:bottom,left:-50].copy()
    img=grayscale(img)
    sum=np.sum(image[50:bottom,left:-50 ])
    if sum>(bottom-50)*(left-50)*125:
        img=255-img
    #print(sum)


    ret, binary = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)

    contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    cv2.drawContours(img, contours, -1, (0, 0, 255), 3)

    cv2.imshow("img", img)
    cv2.waitKey(0)
    cv2.imshow(Home.image_name, img)
    cv2.waitKey(0)
    #cv2.destroyAllWindows()
#endregion

#定位2，成功
def locate2(image):#定位2找到所有数位置

    #region Step 1 先找到纵坐标数字的那一列
    start,end=0,0   #左边一列的数字
    down=0  #下面的数字底部位置

    histogram_row = np.sum(image, axis=1)  # 每一行相加
    for i in range(len(histogram_row)-1,5,-1):
        if histogram_row[i] > image.shape[1] * 255 / 25:
            down = i
            break

    histogram = np.sum(image, axis=0)   #每一列相加
    for i in range(5,len(histogram)):
        if histogram[i]>image.shape[0]*255/25:
            start=i
            break
    #1.1取平均值，若是和平均值相差太多，则肯定结束
    sum=0
    sum_count=0
    for i in range(start,len(histogram)//3):
        sum=sum+histogram[i]
        sum_count=sum_count+1;
        k=histogram[i+1]/(sum/sum_count)
        #print("k",k)
        if k>1.75 or k<0.75:
            end=i
            if end - start > 30:
                print("故障",Home.image_name)
            if end-start>7:
                break
    for i in range(image.shape[0]-1):
        image[i][start]=255
        image[i][end] = 255

    #endregion

#第二步，找到每个数的具体位置
    #2.1取每个白色小块的纵坐标的平均值
    tripe=image[:,start+2:end].copy()
    #print("R-118",tripe.shape)
    numbers=[]#用来装数字的
    high_max=0#所有数的高的最大值
    numbers_matrix=[]#用来装数字的字形矩阵的
    top = 0;
    bottom=0;
    flag=True
    for i in range(0,len(tripe)-10):
        #print("2.2-sum(tripe[i])",np.sum(tripe[i]))

        if np.sum(tripe[i])>100 and flag:#这一行有白色
            top=i
            flag=False
        if np.sum(tripe[i])<100 and (not flag):#这一行没白色
            bottom=i-1
            flag=True
            high_max=(bottom-top) if (bottom-top)>high_max else high_max
            numbers.append(int((top+bottom)/2))

    for i in numbers:#给每个数画横向白线测试
        image[i,:]=255
    image[down,:]=255

    cv2.imshow("search_number"+Home.image_name,image)
    cv2.waitKey(0)
    #cv2.destroyAllWindows()
    return numbers,high_max,start,end,down#返回所有数的纵坐标数组，数的高度，数的左右边



#查找数字
def search_number(image):
    image=image.copy()

    #region Step1 处理图片

    image_original=image.copy()#备份待用
    # 调整宽度，使得变窄，容易读取数字
    rat=400 / image.shape[1]
    image = cv2.resize(image, None, fx=rat, fy=1, interpolation=cv2.INTER_LINEAR)
    #灰度化
    image=grayscale(image)
    #腐蚀
    image=fushi(image)
    #形态学处理--影响不大
    #image=shape_process(image)
    #二值化
    image=threshold(image)
    #endregion

    #region Step 2 定位
    numbers, high_max, start, end, down = locate2(image)
    start = int(start / rat)  # 恢复比率
    end = int(end / rat)  # 恢复比率
    # print(numbers)
    #endregion

    #region Step 3 分割数字
    numbers_image=[]
    i=0
    for item in numbers:
        top=item-high_max//2
        bottom=item + high_max // 2
        img=image_original[top:bottom+2,start:end+2].copy()
        numbers_image.append(img)
        # cv2.imwrite("img2"+str(i)+".png",img)
        # cv2.waitKey(0)
        i=i+1
    #endregion

    return end,down,high_max




#查找折线
def get_line2(image,left,down):#左边和下边
    image_original = image.copy()  # 备份待用
    right,up=0,0    #右边和上面
    # 查找右边和上面
    image_half=image[:image.shape[0]//2,image.shape[1]//2:]
    image_half=grayscale(image_half)

    #print(image_half.shape)
    histogram_row = np.sum(image_half, axis=1)  # 每一行相加
    #print("len行", len(histogram_row))
    for i in range(5,len(histogram_row) - 1):
        if histogram_row[i] !=histogram_row[i-1]:
            up = i+5
            break

    histogram = np.sum(image_half, axis=0)  # 每一列相加
    #print("len列",len(histogram))
    for i in range(len(histogram)-2,0,-1):
        #print(i)
        if histogram[i] !=histogram[i+1]:
            image_half[:, i] = 255
            right = i+image.shape[1]//2-5
            break
    image=image_original.copy()
    #print("分割",image.shape[1],right)


    image[:,0:left]=image[5][5]
    image[:,right:]=image[5][5]
    image[down:,:]=image[5][5]
    image[0:up,:]=image[5][5]

    image_mask=image.copy()


    left = image.shape[1] // 2
    bottom = image.shape[0] // 2
    img = image[50:bottom, left:-50].copy()
    img = grayscale(img)
    sum = np.sum(image[50:bottom, left:-50])
    if sum < (bottom - 50) * (left - 50) * 125:
        image = 255 - image
    #print(sum)

    #要找到在所画图中有，而其他地方没有的

    image_orign=image.copy()
    #上下相减
    for i in range(image.shape[0]-2):
        image[i]=image[i]-image[i+1]

    # for i in range(image.shape[0] - 2):
    #     for j in range(image.shape[1] - 2):
    #         image[i][j] = image[i][j] - image[i ][j+1]

    #print(image.shape)

    #cv2.imshow("image", image   )
    g = image[:, :, 1]
    r = image[:, :, 0]
    b = image[:, :, 2]
    #print("rgb:", r.shape, g.shape, b.shape)

    #image_gray = (r * 0.3 + g * 0.5 + b * 0.2)
    image_gray=cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    ret, image_gray = cv2.threshold(image_gray, 25, 225, cv2.THRESH_BINARY)
   #cv2.imshow("up_and_right",image_gray)
    #cv2.waitKey(0)


    #去除横白线
    image_qu_white=image_gray.copy()

    # print("sum",len(np.sum(image_gray,axis=1)))
    # print("shape[0]",image_gray.shape[0])
    sum_heng=np.sum(image_gray,axis=1)
    for i in range(len(sum_heng)-1):
        if sum_heng[i]> 255*image.shape[1]//3:
            image_qu_white[i,:]=0
    #
    # 去除竖白线
    image_qu_white2 = image_qu_white.copy()

    # print("sum", len(np.sum(image_qu_white2, axis=0)))
    # print("shape[0]", image_qu_white2.shape[0])
    sum_heng2 = np.sum(image_qu_white2, axis=0)
    for i in range(len(sum_heng2) - 1):
        if sum_heng2[i] >255 * image.shape[0] // 5  :
            image_qu_white2[:, i] = 0

    #去除白色小点点
    # 腐蚀或膨胀
    kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT, (1 , 10  ))  # 定义一个10x10的矩形核
    kernel2 = cv2.getStructuringElement(cv2.MORPH_RECT, (10, 30))  # 定义一个10x10的矩形核
    erode = cv2.erode(image_qu_white2, kernel1, 1  )#削去白色  （图片，区域，次数）
    dilate = cv2.dilate(image_qu_white2, kernel2 ,2)#增加白色

    #cv2.imshow("img_qu_white", image_qu_white)
    #cv2.imshow("img_qu_white2", image_qu_white2)
    #cv2.imshow("erode", erode)
    #cv2.imshow("dilate", dilate)
    #cv2.imshow("img",image_gray )
    #cv2.waitKey(0)
    #cv2.destroyAllWindows()


    #掩码操作
    #print("123456",image_mask.shape,dilate.shape)
    dilate=dilate.astype(np.uint8)#类型转换
    #print(dilate.dtype,image_mask.dtype)

    #mask1_hei = cv2.bitwise_not(dilate)
    # cv2.imshow("mask1_hei", mask1_hei)
    # cv2.waitKey(0)
    # cv2.destroyAllWindows()
    result = cv2.bitwise_and(image_mask, image_mask, mask=dilate)
    #cv2.imshow(Home.image_name,result)
    #cv2.waitKey(0)

    return result

def colour_sub(image):
    # image_sub=image[:,:,0]
    # for j in range(3, image.shape[1] - 3):
    #      for i in range(1,image.shape[0]-1):
    #         if all(image[i,j]==image[i,j+1]) and all(image[i,j]==image[i+1,j] ) and all (image[i,j]==image[i+1,   j+1]):
    #             image_sub[i,j]=image_sub[i,j+1]=image[i+1,j+1]=image[i+1,j]=0
    #
    # for j in range(1, image.shape[1] - 1):
    #      for i in range(1,image.shape[0]-1):
    #         if image_sub[i,j]==0:
    #             image[i,j,:]=0
    # cv2.imshow("image_sub",image)
    # cv2.waitKey(0)
    # return image
    image_origal = image.copy()
    image_sub = image[:, :, 0]
    for j in range(4, image.shape[1] - 4):
        for i in range(4, image.shape[0] - 4):
            # 2*2
            if all(image[i, j] == image[i, j + 1]) and all(image[i, j] == image[i + 1, j]) and all(
                    image[i, j] == image[i + 1, j + 1]):
                image_sub[i, j] = image_sub[i, j + 1] = image[i + 1, j + 1] = image[i + 1, j] = 0
            # 4*1
            if all(image[i, j] == image[i, j + 1]) and all(image[i, j] == image[i, j + 2]) and all(
                    image[i, j] == image[i, j + 3]):
                image_sub[i, j] = image_sub[i, j + 1] = image[i, j + 2] = image[i, j + 3] = 0
            if all(image[i, j] == image[i + 1, j]) and all(image[i, j] == image[i + 2, j]) and all(
                    image[i, j] == image[i + 3, j]):
                image_sub[i, j] = image_sub[i + 1, j] = image[i + 2, j] = image[i + 3, j] = 0
    for j in range(1, image.shape[1] - 1):
        for i in range(1, image.shape[0] - 1):
            if image_sub[i, j] == 0:
                image[i, j, :] = 0

    # 去除白色小点点
    # 腐蚀或膨胀
    kernel1 = cv.getStructuringElement(cv.MORPH_RECT, (1, 5))  # 定义一个10x10的矩形核
    kernel2 = cv.getStructuringElement(cv.MORPH_RECT, (1, 5))  # 定义一个10x10的矩形核
    kernel3 = cv.getStructuringElement(cv.MORPH_RECT, (2, 5))  # 定义一个10x10的矩形核
    kernel4 = cv.getStructuringElement(cv.MORPH_RECT, (5, 10))  # 定义一个10x10的矩形核
    erode = cv.erode(image, kernel1, 1)  # 削去白色  （图片，区域，次数）
    return erode

def ColourDistance(rgb_1, rgb_2):
    R_1, G_1, B_1 = rgb_1
    R_2, G_2, B_2 = rgb_2
    rmean = (R_1 + R_2) / 2
    R = R_1 - R_2
    G = G_1 - G_2
    B = B_1 - B_2
    return math.sqrt((2 + rmean / 256) * (R ** 2) + 4 * (G ** 2) + (2 + (255 - rmean) / 256) * (B ** 2))






#第二次精确分割，宁缺毋滥
def second_search(result,image):

    g = result[:, :, 1]
    r = result[:, :, 0]
    b = result[:, :, 2]
    level = 250
    color_one = result[:, :, 1]
    while True:
        ret, gg = cv2.threshold(g, level, 255, cv2.THRESH_BINARY_INV)
        ret, rr = cv2.threshold(r, level, 255, cv2.THRESH_BINARY_INV)
        ret, bb = cv2.threshold(b, level, 255, cv2.THRESH_BINARY_INV)
        # print(gg,gg.shape)
        # print(np.sum(gg).shape)
        gg_sum = np.sum((np.sum(gg))) // 255
        rr_sum = np.sum((np.sum(rr))) // 255
        bb_sum = np.sum((np.sum(bb))) // 255

        level = level - 50
        if gg_sum < image.shape[0] * image.shape[1] - 1000 or rr_sum < image.shape[0] * image.shape[
            1] - 1000 or bb_sum < image.shape[0] * image.shape[1] - 1000:
            print(gg_sum, rr_sum, bb_sum)
            if gg_sum <= rr_sum and gg_sum <= bb_sum:
                color_one = gg
            elif bb_sum <= rr_sum and bb_sum <= gg_sum:
                color_one = bb
            else:
               ret, color_one = rr
            break

    cv2.imshow("color_one",color_one)
    cv2.imshow("r",rr)
    cv2.imshow("g",gg)
    cv2.imshow("b",bb)

    # 反色把黑线换成白线做掩码
    color_one_vease = cv2.bitwise_not(color_one)
    cv2.imshow("color_one_vease", color_one_vease)
#一列一列,从左向右，从上到下如果左边有，先判断上面判断右边

#距离平均大，但是有缓冲，距离缓冲小
    likeness=30



    average=[0,0,0]
    average_count=0

    # cv2.imshow("result_img" + str(average_count), color_one_vease)
    # cv2.waitKey(0)
    flag =True
    abc=True
    for j in range(image.shape[1]):
         for i in range(image.shape[0]):
             if color_one_vease[i][j] > 0:
                         average = average + image[i, j]
                         average_count = average_count + 1
    average=average//average_count
    for j in range(image.shape[1]):
         for i in range(image.shape[0]):
             if ColourDistance(average,image[i,j])>likeness:
                 image[i,j,:]=0




    cv2.imshow("result_img"+Home.image_name, image)
    cv2.imshow("color_one_vease"+Home.image_name, color_one_vease)
    cv2.waitKey(0)
    #cv2.destroyAllWindows()
    return image
